#include "comm.hpp"

// 全局变量init在程序开始时被实例化，触发FIFO的创建
Init init; 

string TransToHex(key_t k)
{
    // 将key_t类型的键转换成十六进制字符串
    char buffer[32];
    snprintf(buffer, sizeof buffer, "0x%x", k);
    return buffer;
}

int main()
{
    // 1. 生成共享内存的唯一键值
    key_t k = ftok(PATH_NAME, PROJ_ID);
    assert(k != -1);
    Log("create key done", Debug) << " server key : " << TransToHex(k) << endl;

    // 2. 创建一个新的共享内存段（如果不存在则创建，设置只允许创建者访问，可读写）
    int shmid = shmget(k, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid == -1)
    {
        perror("shmget"); // 输出错误信息
        exit(1);
    }
    Log("create shm done", Debug) << " shmid : " << shmid << endl;

    // 3. 将共享内存映射到当前进程的地址空间
    char *shmaddr = (char *)shmat(shmid, nullptr, 0);
    Log("attach shm done", Debug) << " shmid : " << shmid << endl;

    // 打开FIFO以读模式
    int fd = OpenFIFO(FIFO_NAME, READ);

    // 循环等待客户端发来的信号
    for(;;)
    {
        // 当FIFO中有数据时，即视为客户端准备好了
        Wait(fd);

        // 临界区：此时假设客户端已将数据写入共享内存
        printf("%s\n", shmaddr);
        if(strcmp(shmaddr, "quit") == 0) break; // 如果收到“quit”，退出循环

        // （注：此处应根据实际情况加入适当的同步措施以保护共享内存区域的并发访问安全）
    }

    // 4. 解除共享内存映射
    int n = shmdt(shmaddr);
    assert(n != -1);

    // 5. 删除共享内存段（即使还有其他进程连接到它）
    n = shmctl(shmid, IPC_RMID, nullptr);
    assert(n != -1);

    // 关闭FIFO文件描述符
    CloseFifo(fd);

    return 0;
}